# coding:utf-8
import functools
from datetime import datetime
import datetime

S, M, U = (1, 1000, 1000000)


def get_now_timestamp(unit='s'):
    """
    将当前时间计算成微秒
    :return: 微妙
    """
    if unit == 'ms':
        divide_number = M
    elif unit == 'us':
        divide_number = U
    else:
        divide_number = S

    return int(datetime.now().timestamp() * divide_number)


get_current_time_by_microsecond = functools.partial(get_now_timestamp, unit='us')


def string_to_time(s, time_format="%Y-%m-%d %H:%M:%S"):
    """
    将字符串转换为时间对象

    Args:
        s (str): 要转换的字符串
        time_format (str, optional): 字符串的时间格式，默认为"%Y-%m-%d %H:%M:%S"

    Returns:
        datetime.datetime: 转换后的时间对象

    Raises:
        TypeError: 如果输入不是字符串类型
    """
    if isinstance(s, str):
        return datetime.strptime(s, time_format)
    else:
        raise TypeError



def time_to_timestamp(d, time_format="%Y-%m-%d %H:%M:%S"):
    """
    将时间转换为时间戳。

    参数：
    d (str 或 datetime): 要转换的时间
    time_format (str, 可选): 时间格式，默认为"%Y-%m-%d %H:%M:%S"

    返回：
    float: 转换后的时间戳

    示例：
    >>> time_to_timestamp('2021-04-01 00:00:00')
    1617196800.0
    >>> time_to_timestamp(datetime(2021, 4, 1, 0, 0, 0))
    1617196800.0
    """

    if isinstance(d, str):
        return string_to_time(d, time_format).timestamp()
    elif isinstance(d, datetime):
        return d.timestamp()
    else:
        raise TypeError



def timestamp_to_string(timestamp, unit='s', fmt="%Y-%m-%d %H:%M:%S"):
    """
    将时间戳转换为指定单位的字符串格式。

    参数：
    timestamp (int): 时间戳
    unit (str, 可选): 时间戳的单位，默认为秒（'s'）
    fmt (str, 可选): 字符串格式，默认为"%Y-%m-%d %H:%M:%S"

    返回：
    str: 转换后的字符串

    示例：
    >>> timestamp_to_string(1617196800, 's', "%Y-%m-%d %H:%M:%S")
    '2021-04-01 00:00:00'
    >>> timestamp_to_string(1617196800, 'ms', "%Y-%m-%d %H:%M:%S")
    '2021-04-01 00:00:00'
    >>> timestamp_to_string(1617196800, 'us', "%Y-%m-%d %H:%M:%S")
    '2021-04-01 00:00:00'
    """

    if unit == 'ms':
        timestamp = timestamp / M
    elif unit == 'us':
        timestamp = timestamp / U
    else:
        timestamp = timestamp / S
    date = datetime.fromtimestamp(timestamp)
    return date.strftime(fmt)


us_timestamp_to_string = functools.partial(timestamp_to_string, unit='us')
ms_timestamp_to_string = functools.partial(timestamp_to_string, unit='ms')


def time_calibration(interval):
    """
    时间校准，根据间隔周期，计算离下一次周期的时间
    :param interval:
    :return:
    """
    now = datetime.now()
    now_seconds = now.second
    now_minutes = now.minute
    microseconds = now.microsecond / 1e6

    seconds_of_this_hour = now_minutes * 60 + now_seconds

    if seconds_of_this_hour < interval:
        offset = interval - seconds_of_this_hour - microseconds
    else:
        offset = interval - (seconds_of_this_hour % interval) - microseconds

    if offset < 0:
        offset = 0

    return offset


def get_month_days(year, month):
    if month == 12:
        next_month = 1
        next_year = year + 1
    else:
        next_month = month + 1
        next_year = year

    current_month_end = datetime.date(next_year, next_month, 1) - datetime.timedelta(days=1)
    return current_month_end.day